home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #26 (Nov 87) / asm lab Formatter / FormNumString.asm < prev    next >
Assembly Source File  |  1987-10-21  |  4KB  |  166 lines

  1. ; FormNumString.asm
  2. ;-------------------
  3. ; by Mike™ Scanlin  29 Dec 1986
  4.  
  5. Xref    FormNumString,GetANumber
  6.  
  7. ;============
  8. FormNumString
  9. ;============
  10. ; format the string representation of a number (integer or real)
  11. ; according to a format string.
  12. ;  input: A0 points to string of a number (which should be in a 
  13. ;         space big enough for formatting result)
  14. ;      A1 points to format string
  15. ;      syntax of format string is [',']d[d]['.'[d[d]]] where ''
  16. ;      denote a constant char and d denotes a digit '0'..'9'
  17. ;      there is no length byte for these strings.
  18. ;        valid strings      invalid strings
  19. ;        3            230.    (230 too big [99 max])
  20. ;            4.0 or 4.        .0    (need a d before '.')
  21. ;        ,3.4            ,.4    (need a d between ',.')
  22. ;        ,12.20            0.123    (123 too big)
  23. ; output: A0 points to formatted string of a number
  24. ;      A1 points to first byte after format string
  25.  
  26.     MOVEM.L        D0-D5/A2,-(SP)
  27.     CMPI.B        #',',(A1)
  28.     BNE.S        @6
  29.     ADDA        #1,A1
  30. ;do commas
  31. ;first find out if there is a decimal point in the string
  32.     MOVEQ        #0,D0
  33.     MOVE.B        (A0),D0        ;length of string
  34.     MOVE        D0,D2        ;save in case it's and int
  35.     SUBQ        #1,D0        ;loop control
  36. ;D0 counts how many digits from the end of the string to the
  37. ;decimal point (including the decimal point -- which is why
  38. ;it starts out as 1 and not 0). If the number is an int, then D0=0
  39.     MOVEQ        #1,D1
  40. @1    CMPI.B        #'.',1(A0,D0)    ;find a dec point, it's a real
  41.     BEQ.S        @2
  42.     ADDQ        #1,D1
  43.     DBRA        D0,@1
  44. ;it's an integer
  45.     MOVE        D2,D0
  46.     MOVEQ        #0,D1
  47. ;now add some commas
  48. @2    MOVE        D1,D5        ;save length of fraction
  49.     MOVEQ        #3,D2        ;# of digits until next comma
  50.     SUBQ        #1,D0
  51. @3    ADDQ        #1,D1        ;total len, from end to cur pos
  52.     SUBQ        #1,D2
  53.     BNE.S        @5
  54.     MOVE        D0,D3
  55.     MOVE.B        (A0,D0),D0
  56.     BSR        IsItADigit    ;test next digit
  57.     BNE.S        @6
  58.     MOVE        D3,D0
  59. ;move some chars, add a comma, increase string length.
  60.     MOVE        D1,D4        ;loop control
  61.     SUBQ        #1,D4
  62.     LEA        1(A0,D0),A2
  63. @4    MOVE.B        (A2,D4),1(A2,D4)
  64.     DBRA        D4,@4
  65.     MOVE.B        #',',(A2)
  66.     ADDI.B        #1,(A0)
  67.     ADDQ        #1,D1        ;for the comma
  68.     MOVEQ        #3,D2        ;reset counter
  69. @5    DBRA        D0,@3
  70. ;get next byte of format string
  71. @6    BSR.S        GetANumber    ;D0 = q    
  72.     BMI.S        @16        ;no q provided -- leave
  73.     MOVEQ        #0,D2
  74.     MOVE.B        (A0),D2        ;length of string
  75.     MOVE        D2,D1
  76.     SUB        D5,D1        ;D1=len of quotient now
  77.     SUB        D1,D0
  78.     BMI.S        @10
  79.     BEQ.S        @10
  80.     ADD.B        D0,(A0)        ;increase length by D0 spaces
  81. ;add D0 # of preceeding spaces
  82. @7    LEA        1(A0,D0),A2
  83.     SUBQ        #1,D2
  84. @8    MOVE.B        1(A0,D2),(A2,D2)
  85.     DBRA        D2,@8
  86.     SUBQ        #1,D0
  87. @9    MOVE.B        #' ',1(A0,D0)
  88.     DBRA        D0,@9
  89. ;do remainder
  90. @10    CMPI.B        #'.',(A1)
  91.     BNE.S        @16
  92.     ADDA        #1,A1
  93. ;make sure there is a decimal point already
  94.     LEA        1(A0),A2
  95.     MOVEQ        #0,D0
  96.     MOVE.B        (A0),D0
  97.     SUBQ        #1,D0
  98. @11    CMP.B        #'.',(A2)+
  99.     BEQ.S        @12
  100.     DBRA        D0,@11
  101.     MOVE.B        #'.',(A2)+
  102.     ADD.B        #1,(A0)
  103. @12    BSR.S        GetANumber
  104.     BMI.S        @16        ;no r provided -- leave
  105. ;D0 is how many digits they want. D5 is what we've already got.
  106. @13    SUBQ        #1,D5
  107. @14    CMP        D5,D0
  108.     BEQ.S        @16
  109.     BPL.S        @15
  110.     SUB.B        #1,(A0)
  111.     BRA.S        @13
  112. @15    MOVE.B        #'0',(A2,D5)    ;add a zero
  113.     ADD.B        #1,(A0)
  114.     ADDQ        #1,D5
  115.     BRA.S        @14
  116. @16    MOVEM.L        (SP)+,A2/D0-D5
  117.     RTS
  118.  
  119. ;=========
  120. GetANumber
  121. ;=========
  122. ; convert a one or two digit ASCII integer into its numerical form
  123. ;  input: A1 points to digit(s)
  124. ; output: D0 is the decimal equivalent (-1 if A1 didn't point to a digit)
  125. ;      A1 points to byte after digit(s)
  126. ;      Z and N flags reflect the value of D0
  127.     MOVEM.L        D1-D2,-(SP)
  128.     MOVEQ        #0,D0
  129.     MOVE.B        (A1),D0
  130. @1    BSR.S        IsItADigit
  131.     BEQ.S        @2
  132.     MOVEQ        #-1,D0
  133.     BRA.S        @4
  134. @2    ADDA        #1,A1
  135.     MOVE        D0,D1        ;save first digit
  136.     MOVE.B        (A1),D0
  137.     BSR.S        IsItADigit
  138.     BEQ.S        @3
  139.     MOVE        D1,D0
  140.     BRA.S        @4
  141. @3    ADDA        #1,A1
  142.     ADD        D1,D1        ;multiply first digit by 10
  143.     MOVE        D1,D2
  144.     ADD        D2,D2
  145.     ADD        D2,D2
  146.     ADD        D2,D1
  147.     ADD        D1,D0        ;add to second digit
  148. @4    MOVEM.L        (SP)+,D1-D2
  149.     TST        D0
  150.     RTS
  151.  
  152. ;=========
  153. IsItADigit
  154. ;=========
  155. ; If the ASCII byte in D0 is in '0'..'9' it's value [0..9] 
  156. ; is returned in D0. If D0 is a digit, all flags are set.
  157.     CMPI.B        #'0',D0
  158.     BLT.S        @1
  159.     CMPI.B        #'9',D0
  160.     BGT.S        @1
  161.     SUBI.B        #'0',D0
  162.     MOVE        #-1,CCR        ;set all flags
  163.     RTS
  164. @1    MOVE        #0,CCR        ;clear all flags
  165.     RTS
  166.